package com.ljf.authority.domain.validator;

import com.ljf.authority.domain.repository.AuthorityBaseApiTabulationRepository;
import com.ljf.authority.domain.repository.AuthorityBaseMenuTabulationRepository;
import com.ljf.authority.domain.repository.AuthorityDatPermissionGroupRepository;
import com.ljf.authority.dto.command.*;
import com.ljf.authority.dto.query.AuthorityBaseApiTabulationQuery;
import com.ljf.authority.dto.query.AuthorityBaseMenuTabulationQuery;
import com.ljf.authority.dto.query.AuthorityDatPermissionGroupQuery;
import com.ljf.authority.enums.AuthorityBaseMenuTabulationLevelEnum;
import com.ljf.authority.model.AuthorityBaseMenuTabulation;
import com.ljf.authority.vo.AuthorityBaseMenuTabulationVO;
import com.ljf.common.domain.validator.BasisValidator;
import com.ljf.common.enums.ActivationEnum;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.EnumUtil;
import com.ljf.common.utils.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 菜单列表定义  业务校验
 *
 * @author LJF
 * @since 2024-10-17
 */
@Component
@AllArgsConstructor
public class AuthorityBaseMenuTabulationValidator extends BasisValidator<AuthorityBaseMenuTabulationQuery, AuthorityBaseMenuTabulationCommand, AuthorityBaseMenuTabulationVO, AuthorityBaseMenuTabulation, AuthorityBaseMenuTabulationRepository> {

    private final AuthorityBaseApiTabulationRepository apiTabulationRepository;
    private final AuthorityDatPermissionGroupRepository permissionGroupRepository;

    /**
     * 权限按钮 业务校验
     *
     * @param componentUrl
     * @throws ServiceException
     */
    public void checkButton(String componentUrl) throws ServiceException {
        if (StringUtil.isEmpty(componentUrl)) {
            throw new ServiceException("权限菜单配置异常:组件地址不能为空");
        }
    }

    /**
     * 新增接口 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    @Override
    public void checkAdd(AuthorityBaseMenuTabulationCommand command) throws ServiceException {
        super.checkAdd(command);
        String code = command.getCode();
        if (code.contains("-")) {
            throw new ServiceException("校验异常: 编码不能包含【-】字符");
        }
        String name = command.getLabel();
        if (name.contains("-")) {
            throw new ServiceException("校验异常: 名称不能包含【-】字符");
        }
        if (StringUtil.isNotEmpty(command.getPCode())) {
            AuthorityBaseMenuTabulationVO pMenuTabulation = repository.selectOne(
                    AuthorityBaseMenuTabulationQuery.builder().code(command.getPCode()).build(),
                    "校验异常: 父级编码不存在",
                    "数据异常: 编码存在重复"
            );
            code = pMenuTabulation.getCode() + '-' + code;
            name = pMenuTabulation.getName() + '-' + name;
        }
        int count = repository.count(AuthorityBaseMenuTabulationQuery.builder().code(code).build());
        if (count > 0) {
            throw new ServiceException("校验异常: 编码已存在");
        }
        if (code.length() > 60) {
            throw new ServiceException("校验异常: 编码不能大于60个字符");
        }
        if (name.length() > 30) {
            throw new ServiceException("校验异常: 名称不能大于30个字符");
        }
    }

    /**
     * 批量删除接口 业务校验
     *
     * @param ids
     * @throws ServiceException
     */
    @Override
    public void checkDeleteBatch(List<Long> ids) throws ServiceException {
        super.checkDeleteBatch(ids);
        List<AuthorityBaseMenuTabulationVO> modelList = repository.selectListByIds(ids);
        if (modelList.size() != ids.size()) {
            throw new ServiceException("校验异常: 数据不存在, 请刷新后重试");
        }
        List<String> codeList = modelList.stream().map(AuthorityBaseMenuTabulationVO::getCode).distinct().collect(Collectors.toList());
        int count = repository.count(AuthorityBaseMenuTabulationQuery.builder().pCodeList(codeList).build());
        if (count != 0) {
            throw new ServiceException("校验异常: 存在使用中的菜单节点");
        }
    }

    /**
     * 更新接口 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    @Override
    public void checkEdit(AuthorityBaseMenuTabulationCommand command) throws ServiceException {
        super.checkEdit(command);
        String code = command.getCode();
        if (code.contains("-")) {
            throw new ServiceException("校验异常: 编码不能包含【-】字符");
        }
        String name = command.getLabel();
        if (name.contains("-")) {
            throw new ServiceException("校验异常: 名称不能包含【-】字符");
        }
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        if (model == null) {
            throw new ServiceException("校验异常: 数据不存在, 请刷新后重试");
        }
        if (StringUtil.isNotEmpty(model.getPCode())) {
            AuthorityBaseMenuTabulationVO pMenuTabulation = repository.selectOne(
                    AuthorityBaseMenuTabulationQuery.builder().code(model.getPCode()).build(),
                    "校验异常: 父级编码不存在",
                    "数据异常: 编码存在重复"
            );
            code = pMenuTabulation.getCode() + '-' + code;
            name = pMenuTabulation.getName() + '-' + name;
        }
        if (!Objects.equals(code, model.getCode()) || !Objects.equals(name, model.getName())) {
            if (!Objects.equals(code, model.getCode())) {
                int count = repository.count(AuthorityBaseMenuTabulationQuery.builder().code(code).build());
                if (count > 0) {
                    throw new ServiceException("校验异常: 编码已存在");
                }
                if (code.length() > 60) {
                    throw new ServiceException("校验异常: 编码不能大于60个字符");
                }
            }
            if (!Objects.equals(name, model.getName()) && name.length() > 30) {
                throw new ServiceException("校验异常: 名称不能大于30个字符");
            }
        }
        else {
            throw new ServiceException("校验异常: 编码和名称一致, 无需更改");
        }
    }

    /**
     * 根据ID查询菜单树排序 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQuerySortById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 修改菜单列表排序 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditSort(AuthorityBaseMenuTabulationSortCommand command) throws ServiceException {
        if (CollectionUtil.isEmpty(command.getSortList())) {
            throw new ServiceException("校验异常: 排序不能为空");
        }
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        if (model == null) {
            throw new ServiceException("校验异常: 请选择数据进行处理");
        }
        if (model.getLevel() == null) {
            throw new ServiceException("数据异常: 层级为空");
        }
        AuthorityBaseMenuTabulationQuery query = AuthorityBaseMenuTabulationQuery.builder()
                .level(model.getLevel())
                .build();
        if (!Objects.equals(model.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MAIN_MENU.getCode())) {
            if (StringUtil.isEmpty(model.getPCode())) {
                throw new ServiceException("数据异常: 上级编码为空");
            }
            query.setPCode(model.getPCode());
        }
        int count = repository.count(query);
        if (count != command.getSortList().size()) {
            throw new ServiceException("数据异常: 排序数据不全, 请刷新后重试");
        }
    }

    /**
     * 根据ID查询菜单树明细 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryDetailById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 修改菜单列表明细 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditDetail(AuthorityBaseMenuTabulationDetailCommand command) throws ServiceException {
        AuthorityBaseMenuTabulationVO model = repository.selectById(command.getId());
        if (model == null) {
            throw new ServiceException("校验异常: 数据不存在, 请刷新后重试");
        }
        else if (Objects.equals(model.getLevel(), AuthorityBaseMenuTabulationLevelEnum.MENU_CLASSIFICATION.getCode())) {
            throw new ServiceException("校验异常: 该层级无明细");
        }
    }

    /**
     * 根据ID查询菜单关联后端 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryBackendById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 修改菜单列表关联后端 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditBackend(AuthorityBaseMenuTabulationBackendCommand command) throws ServiceException {
        if (repository.countById(command.getId()) == 0) {
            throw new ServiceException("校验异常: 数据不存在, 请刷新后重试");
        }
        if (CollectionUtil.isNotEmpty(command.getBackendList())) {
            int count = apiTabulationRepository.count(
                    AuthorityBaseApiTabulationQuery.builder()
                            .codeList(command.getBackendList())
                            .build()
            );
            if (count != command.getBackendList().size()) {
                throw new ServiceException("校验异常: 后端编码不存在");
            }
        }
    }

    /**
     * 根据ID查询菜单按钮方法 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryMethodById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 修改菜单列表按钮方法 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditMethod(AuthorityBaseMenuTabulationMethodCommand command) throws ServiceException {
        if (repository.countById(command.getId()) == 0) {
            throw new ServiceException("校验异常: 后端编码不存在或者未激活");
        }
    }

    /**
     * 修改菜单列表激活状态 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditActivation(AuthorityBaseMenuTabulationActivationCommand command) throws ServiceException {
        super.checkEditActivation(command.getIds(), command.getActivation());
    }

    /**
     * 修改菜单列表关联权限组 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditPermissionGroup(AuthorityBaseMenuTabulationPermissionGroupCommand command) throws ServiceException {
        if (repository.countById(command.getId()) == 0) {
            throw new ServiceException("校验异常: 数据不存在, 请刷新后重试");
        }
        if (CollectionUtil.isNotEmpty(command.getPermissionGroupList())) {
            int count = permissionGroupRepository.count(
                    AuthorityDatPermissionGroupQuery.builder()
                            .codeList(command.getPermissionGroupList())
                            .build()
            );
            if (count != command.getPermissionGroupList().size()) {
                throw new ServiceException("校验异常: 权限组不存在或者未激活");
            }
        }
    }

    /**
     * 根据ID查询菜单权限组 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryPermissionGroupById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

}
